import java.util.PriorityQueue;

class MyTimerTask implements Comparable<MyTimerTask>{
    private long time;
    private Runnable runnable;
    public MyTimerTask(Runnable runnable,long delay){
        this.runnable=runnable;
        this.time=System.currentTimeMillis()+delay;
    }
    public long getTime(){
        return time;
    }
    public void run(){
        runnable.run();
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time-o.time);
    }
}



class MyTimer{
    private Object lock=new Object();
        PriorityQueue<MyTimerTask> queue=new PriorityQueue<>();
        public MyTimer(){
            Thread t=new Thread(()->{
               while (true){
                   synchronized (lock){
                       while (queue.isEmpty()){
                           try {
                             lock.wait();
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       }
                       MyTimerTask task=queue.peek();
                       if(System.currentTimeMillis()>=task.getTime()) {
                           task.run();
                           queue.poll();
                       }
                       else {
                           try {
                               lock.wait(task.getTime()-System.currentTimeMillis());
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       }
               }
               }
            });
            t.start();
        }

        public void schedule(Runnable runnable,long delay){
            synchronized (lock){
                MyTimerTask myTimerTask=new MyTimerTask(runnable,delay);
                queue.offer(myTimerTask);
                lock.notify();
            }
        }
}



public class Demo3 {
    public static void main(String[] args) {
        MyTimer myTimer=new MyTimer();
        myTimer.schedule(()->{
            System.out.println("hello 3000");
        },3000);
        myTimer.schedule(()->{
            System.out.println("hello 2000");
        },2000);
        myTimer.schedule(()->{
            System.out.println("hello 1000");
        },1000);

    }
}
